/**
 * 
 */
package com.nari.heatshare.service;

import java.io.File;
import java.io.RandomAccessFile;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.TransformerUtils;
import org.apache.commons.lang3.StringUtils;

import com.nari.baseinfo.dao.IBuildingDao;
import com.nari.baseinfo.dao.ICommunityDao;
import com.nari.baseinfo.dao.IConcentratorDao;
import com.nari.baseinfo.dao.IHeatRoomDao;
import com.nari.baseinfo.model.IConcentrator;
import com.nari.baseinfo.model.IHeatRoom;
import com.nari.basic.model.IUser;
import com.nari.basic.utils.sysmgr.UserRoleUtil;
import com.nari.coreframe.service.GenericServiceImpl;
import com.nari.heatshare.dao.IAssignMeterDao;
import com.nari.heatshare.dao.IAssignMeterDataGatherDao;
import com.nari.heatshare.dao.springjdbc.IAssignMeterDataJdbcDao;
import com.nari.heatshare.model.IAssignMeter;
import com.nari.heatshare.model.IAssignMeterDataGather;
import com.nari.heatshare.utils.MeterDataTransitionUtil;
import com.nari.heatshare.utils.MeterDataTxtGenerator;
import com.nari.heatshare.utils.queryvo.AssignMeterDataCustomizedQuery;
import com.nari.platform.date.CalendarUtils;
import com.nari.platform.model.PageCond;
import com.nari.platform.model.ResponseMsg;
import com.nari.platform.model.ResultWithPageCond;
import com.nari.platform.utils.CommercialHighPrecisionArith;
import com.nari.platform.utils.NumberSystemConversion;
import com.sohoometer.web.bean.AssignDataWithInfo;
import com.sohoometer.web.bean.FaultType;
import com.sohoometer.web.bean.QuestionData;
import com.sohoometer.web.bean.QuestionDataSet;

/**
 * 
 * @author Xiaopeng
 * @date 2013-8-18
 */
public class AssignMeterDataGatherServiceImpl extends GenericServiceImpl<IAssignMeterDataGather, String>
		implements IAssignMeterDataGatherService {
	private ICommunityDao iCommunityDao;
	private IBuildingDao iBuildingDao;
	private IHeatRoomDao iHeatRoomDao;
	private IAssignMeterDao iAssignMeterDao;
	private IConcentratorDao iConcentratorDao;
	private IAssignMeterDataJdbcDao iAssignMeterDataJdbcDao;
	private IAssignMeterDataStatisticsService iAssignMeterDataStatisticsService;
	private String tempSavePath;

	/**
	 * 分页查询分配表数据列表
	 * @param concentratorNo 集中器号(可选)
	 * @param startDate 起始抄表时间(可选)
	 * @param endDate 终止抄表时间(可选)
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-9-2
	 */
	public ResultWithPageCond<IAssignMeterDataGather> queryMeterDataPage(String concentratorNo, 
			Date startDate, Date endDate, PageCond pageCond) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryMeterDataPage(concentratorNo, startDate, endDate, pageCond);
	}
	
	/**
	 * 根据分配表数据的增删改操作，同步更新任务批次统计信息
	 * @param concentratorNo
	 * @param recordTime
	 * @param dataType 分配表数据的数据类型
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2015-1-17
	 */
	private void updateUploadBatch4MeterDataModify(String concentratorNo, Date recordTime, 
			Integer dataType) throws Exception {
//		IAssignMeterDataStatistics amdStatis = iAssignMeterDataStatisticsService.queryStatisByUploadMission(concentratorNo, recordTime);
		//1、若为掌机数据、TXT上传数据或未知数据，且任务批次统计未删除，才执行任务批次统计更新
		//2、其他类型数据：平滑数据、定点上传数据，直接执行任务批次统计更新
//		if(((dataType==null || dataType==1 || dataType==3) && amdStatis!=null) 
//				|| (dataType!=null && dataType==0)
//				|| (dataType!=null && dataType==2)) {
//			iAssignMeterDataStatisticsService.saveOrUpdateAmdStatis(concentratorNo, recordTime);
//		}
		iAssignMeterDataStatisticsService.saveOrUpdateAmdStatis(concentratorNo, recordTime);
	}
	
	/**
	 * 新增或修改分配表数据
	 * @param meterData
	 * 说明：新增分配表数据时，若表号相同、上传时间相同，则认为是重复数据，不予保存数据
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-9-25
	 */
	public ResponseMsg saveOrUpdateMeterData(IAssignMeterDataGather meterData) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		//更新数据的任务批次标识
		String concentratorNo = meterData.getConcentratorNo();
		Date recordTime = meterData.getRecordTime();
		Integer dataType = null;
		//更新前的数据的任务批次标识
		String srcConcentratorNo = null;
		Date srcRecordTime = null;
		boolean uploadBatchModify = false;
		if(meterData.getId()!=null && !"".equals(meterData.getId())) {
			IAssignMeterDataGather srcMeterData = this.getiGenericDao().queryEntityById(meterData.getId());
			if(srcMeterData != null) {
				srcConcentratorNo = srcMeterData.getConcentratorNo();
				srcRecordTime = srcMeterData.getRecordTime();
				//数据修改，不能更改数据的类型
				dataType = srcMeterData.getDataType();
				//比对任务批次标识信息，若任务批次信息变更，则要执行任务批次的统计更新
				if(!srcConcentratorNo.equals(concentratorNo) 
						|| !CalendarUtils.parseDateToString(srcRecordTime).equals(CalendarUtils.parseDateToString(recordTime))) {
					uploadBatchModify = true;
				}
			}
		}
		//更新分配表数据
		ResponseMsg rmsg = iAssignMeterDataGatherDao.saveOrUpdateMeterData(meterData);
		//更新分配表任务批次统计信息
		if(rmsg.isSuccess()) {
			this.updateUploadBatch4MeterDataModify(concentratorNo, recordTime, dataType);
			//若任务批次发生变更，则更新相应任务批次的统计信息
			if(uploadBatchModify) {
				this.updateUploadBatch4MeterDataModify(srcConcentratorNo, srcRecordTime, dataType);
			}
		}
		return rmsg;
	}
	
	/**
	 * 删除分配表数据，并更新对应的任务批次信息
	 * @param meterDataUID
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2015-1-17
	 */
	public ResponseMsg deleteMeterDataByUID(String meterDataUID) throws Exception {
		IAssignMeterDataGather meterData = this.getiGenericDao().queryEntityById(meterDataUID);
		if(meterData == null) {
			return ResponseMsg.getInstance(false, "分配表数据不存在！");
		}
		//任务标识信息
		String concentratorNo = meterData.getConcentratorNo();
		Date recordTime = meterData.getRecordTime();
		Integer dataType = meterData.getDataType();
		//删除分配表数据
		this.getiGenericDao().deleteEntityById(meterDataUID);
		//更新分配表任务批次统计信息
		this.updateUploadBatch4MeterDataModify(concentratorNo, recordTime, dataType);
		return ResponseMsg.getInstance(true);
	}
	
	/**
	 * 批量新增或修改分配表数据
	 * @param meterDataList
	 * 说明：新增分配表数据时，若表号相同、上传时间相同，则认为是重复数据，不予保存数据
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-9-25
	 */
	public ResponseMsg saveOrUpdateMeterDataBatch(List<IAssignMeterDataGather> meterDataList) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.saveOrUpdateMeterDataBatch(meterDataList);
	}
	
	/**
	 * 统计某个分摊域下对应某个上传日期的分配表数据上传率(百分比%)
	 * @param shareAreaUID 分摊域(必填)
	 * @param readTime 上传日期(必填)
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-9-25
	 */
	public double calcUploadPercentByShareArea(String shareAreaUID, 
			Date readTime) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.calcUploadPercentByShareArea(shareAreaUID, readTime);
	}
	
	/**
	 * 统计某个集中器下对应某个上传日期的分配表数据上传率(百分比%)
	 * @param concentratorNo 集中器号(必填)
	 * @param readTime 上传日期(必填)
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-9-25
	 */
	public double calcUploadPercentByConcentrator(String concentratorNo, 
			Date readTime) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.calcUploadPercentByConcentrator(concentratorNo, readTime);
	}
	
	/**
	 * 根据分摊域分页查询所属分配表数据
	 * @param shareAreaUID 分摊域唯一标识(必须)
	 * @param seriousNum 分配表表号(可选)
	 * @param readTime 上传时间(可选)
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-1
	 */
	public ResultWithPageCond<IAssignMeterDataGather> queryMeterDataPageByAreaUID(String shareAreaUID, 
			String seriousNum, Date readTime, PageCond pageCond) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryMeterDataPageByAreaUID(shareAreaUID, seriousNum, readTime, pageCond);
	}
	
	/**
	 * 根据分配表表表号、上传日期查询历史数据
	 * @param seriousNum 分配表表号
	 * @param readTime 上传日期
	 * @param dataLimit 取回历史数据的条数，若不限制，则取回所有历史数据
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-14
	 */
	public List<IAssignMeterDataGather> queryHistoryMeterData(String seriousNum, 
			Date readTime, Integer dataLimit) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryHistoryMeterData(seriousNum, readTime, dataLimit);
	}
	
	/**
	 * 新增分配表表平滑数据(包括人工干预数据和系统自动平滑数据)
	 * @param seriousNum 分配表表号
	 * @param readTime 上传时间
	 * @param readNum 分配表读数
	 * @param backTmperature 背板温度
	 * @param fontTemperature 前板温度
	 * @return 返回平滑数据的ID
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-15
	 */
	public String saveTransitionMeterData(String seriousNum, Date readTime, 
			double readNum, double backTmperature, double fontTemperature) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.saveTransitionMeterData(seriousNum, readTime, readNum, backTmperature, fontTemperature);
	}
	
	/**
	 * 自动平滑分配表数据
	 * @param shareAreaUID
	 * @param startDate
	 * @param endDate
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-15
	 */
	public ResponseMsg saveAutoTransitionMeterData(String shareAreaUID, Date startDate, 
			Date endDate) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		//查询分摊域下的热用户列表
		List<IHeatRoom> roomList = this.iHeatRoomDao.queryHeatRoomsByBelongs(null, null, shareAreaUID, null);
		for(IHeatRoom heatRoom: roomList) {
			/**	校验参与计量收费热用户的分配表，及分配表数据	**/
			if(heatRoom.getIfMeasureCharge() == 2) {
				//热用户所属的分配表
				List<IAssignMeter> meterList = iAssignMeterDao.queryAssignMetersByBelongs(null, null, null, heatRoom.getId());
				if(meterList==null || meterList.size()==0) {
					return ResponseMsg.getInstance(false, "缺少热用户对应的分配表信息，数据无法平滑！");
				}
				for(IAssignMeter assignMeter: meterList) {
					//分配表数据完整性校验 - 对应于分摊周期起始日期的分配表数据检查
					long startAssignMeterDataNum = iAssignMeterDataGatherDao.countMeterDataByCond(assignMeter.getSeriousNum(), startDate);
					if(startAssignMeterDataNum <= 0) {
						//取前三次历史数据，作为数据平滑的依据
						List<IAssignMeterDataGather> historyMeterDatas = this.queryHistoryMeterData(assignMeter.getSeriousNum(), startDate, 3);
						if(historyMeterDatas.size() < 2) {
							String msg = "截至日期到" + CalendarUtils.parseDateToString(startDate)
									+"，表号为" + assignMeter.getSeriousNum()
									+ "的分配表缺少足够的历史数据(至少2次以上)，数据无法平滑！";
							return ResponseMsg.getInstance(false, msg);
						}
						//平滑数据
						this.saveAutoGenerateTransitionData(historyMeterDatas, startDate);
					}
					//分配表数据完整性校验 - 对应于分摊周期结束日期的分配表数据检查
					long endAssignMeterDataNum = iAssignMeterDataGatherDao.countMeterDataByCond(assignMeter.getSeriousNum(), endDate);
					if(endAssignMeterDataNum <= 0) {
						//取前三次历史数据，作为数据平滑的依据
						List<IAssignMeterDataGather> historyMeterDatas = this.queryHistoryMeterData(assignMeter.getSeriousNum(), endDate, 3);
						if(historyMeterDatas.size() < 2) {
							String msg = "截至日期到" + CalendarUtils.parseDateToString(endDate)
									+"，表号为" + assignMeter.getSeriousNum()
									+ "的分配表缺少足够的历史数据(至少2次以上)，数据无法平滑！";
							return ResponseMsg.getInstance(false, msg);
						}
						//平滑数据
						this.saveAutoGenerateTransitionData(historyMeterDatas, endDate);
					}
				}
			}
		}
		return ResponseMsg.getInstance(true, "");
	}
	
	/**
	 * 依据历史数据，按照等差数列的方式生成平滑数据
	 * @param historyMeterDatas 历史数据(2=<历史数据<=3)
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-15
	 */
	private void saveAutoGenerateTransitionData(List<IAssignMeterDataGather> historyMeterDatas, 
			Date recordTime) throws Exception {
		//分配表表号
		String seriousNum = historyMeterDatas.get(0).getSeriousNum();
		//平滑读数
		double transitionReadNum = 0;
		//背板温度均值
		double avgBackTmperature = 0;
		//前板温度均值
		double avgFontTemperature = 0;
		if(historyMeterDatas.size() == 2) {
			//每天的步阶值
			double perDayGradeValue = MeterDataTransitionUtil.calcGradeValueByDay(historyMeterDatas.get(1).getReadNum(), 
					historyMeterDatas.get(1).getRecordTime(), 
					historyMeterDatas.get(0).getReadNum(), 
					historyMeterDatas.get(0).getRecordTime());
			//计算平滑读数
			transitionReadNum = MeterDataTransitionUtil.calcTransitionValue(historyMeterDatas.get(1).getReadNum(), 
					historyMeterDatas.get(1).getRecordTime(), 
					recordTime, perDayGradeValue);
			//背板温度求和
			BigDecimal backTmperatureSum = new BigDecimal(historyMeterDatas.get(1).getBackTmperature())
					.add(new BigDecimal(historyMeterDatas.get(0).getBackTmperature()));
			//计算背板温度均值
			avgBackTmperature = backTmperatureSum
					.divide(new BigDecimal("2"))
					.doubleValue();
			//前板温度求和
			BigDecimal fontTemperatureSum = new BigDecimal(historyMeterDatas.get(1).getFontTemperature())
					.add(new BigDecimal(historyMeterDatas.get(0).getFontTemperature()));
			//计算前板温度均值
			avgFontTemperature = fontTemperatureSum
					.divide(new BigDecimal("2"))
					.doubleValue();
		} else if(historyMeterDatas.size() == 3) {
			//每天的步阶值一
			double perDayGradeValue1 = MeterDataTransitionUtil.calcGradeValueByDay(historyMeterDatas.get(1).getReadNum(), 
					historyMeterDatas.get(1).getRecordTime(), 
					historyMeterDatas.get(0).getReadNum(), 
					historyMeterDatas.get(0).getRecordTime());
			//每天的步阶值二
			double perDayGradeValue2 = MeterDataTransitionUtil.calcGradeValueByDay(historyMeterDatas.get(2).getReadNum(), 
					historyMeterDatas.get(2).getRecordTime(), 
					historyMeterDatas.get(1).getReadNum(), 
					historyMeterDatas.get(1).getRecordTime());
			//取平均的每天步阶值
			BigDecimal perDayGradeValueSum = new BigDecimal(perDayGradeValue1)
					.add(new BigDecimal(perDayGradeValue2));
			double avgPerDayGradeValue = perDayGradeValueSum
					.divide(new BigDecimal("2"))
					.doubleValue();
			//计算平滑读数
			transitionReadNum = MeterDataTransitionUtil.calcTransitionValue(historyMeterDatas.get(2).getReadNum(), 
					historyMeterDatas.get(2).getRecordTime(), 
					recordTime, avgPerDayGradeValue);
			//背板温度求和
			BigDecimal backTmperatureSum = new BigDecimal(historyMeterDatas.get(2).getBackTmperature())
					.add(new BigDecimal(historyMeterDatas.get(1).getBackTmperature()))
					.add(new BigDecimal(historyMeterDatas.get(0).getBackTmperature()));
			//计算背板温度均值
			avgBackTmperature = backTmperatureSum
					.divide(new BigDecimal("3"), new MathContext(5, RoundingMode.HALF_UP))
					.doubleValue();
			//前板温度求和
			BigDecimal fontTemperatureSum = new BigDecimal(historyMeterDatas.get(2).getFontTemperature())
					.add(new BigDecimal(historyMeterDatas.get(1).getFontTemperature()))
					.add(new BigDecimal(historyMeterDatas.get(0).getFontTemperature()));
			//计算前板温度均值
			avgFontTemperature = fontTemperatureSum
					.divide(new BigDecimal("3"), new MathContext(5, RoundingMode.HALF_UP))
					.doubleValue();
		}
		this.saveTransitionMeterData(seriousNum, recordTime, transitionReadNum, avgBackTmperature, avgFontTemperature);
	}
	
	/**
	 * 通过集中器上传批次任务(集中器号、抄表日期)分页查询分配表数据
	 * @param concentratorNo 任务批次上传的集中器号
	 * @param recordTime 任务批次上传的抄表日期
	 * @param seriousNum 分配表表号(可选)
	 * @param startDate 上传日期起始日期(可选)
	 * @param endDate 上传日期结束日期(可选)
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-25
	 */
	public ResultWithPageCond<IAssignMeterDataGather> queryMeterDataPageByUploadBatch(String concentratorNo, 
			Date recordTime, String seriousNum, Date startDate, Date endDate, 
			PageCond pageCond) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryMeterDataPageByUploadBatch(concentratorNo, recordTime, seriousNum, startDate, endDate, pageCond);
	}
	
	/**
	 * 分配表数据的合规性检查，并将不合规的分配表数据ID列表返回
	 * @param meterDataList
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-25
	 */
	public String checkMeterDataLegality(List<IAssignMeterDataGather> meterDataList) throws Exception {
		String illegalIDList = "";
		if(meterDataList!=null && meterDataList.size()>0) {
			for(int index=0; index<meterDataList.size(); index++) {
				IAssignMeterDataGather meterData = meterDataList.get(index);
				if(!this.checkMeterDataRational(meterData)) {
					illegalIDList += meterData.getId() + ",";
				}
			}
			if(illegalIDList.length() > 0) {
				illegalIDList = illegalIDList.substring(0, illegalIDList.length()-1);
			}
		}
		return illegalIDList;
	}
	
	/**
	 * 通过TXT上传的文件ID分页查询分配表数据
	 * @param dataFileUID TXT文件ID(必选)
	 * @param seriousNum 分配表号
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-29
	 */
	public ResultWithPageCond<IAssignMeterDataGather> queryMeterDataPageByFileID(String dataFileUID, 
			String seriousNum, PageCond pageCond) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryMeterDataPageByFileID(dataFileUID, seriousNum, pageCond);
	}
	
//	/**
//	 * 根据相关任务批次、及分配表档案资料查询分配表数据的成功上传数
//	 * @param concentratorNo
//	 * @param recordTime
//	 * @param dataType
//	 * @return
//	 * @throws Exception
//	 * @author Xiaopeng
//	 * @date 2014-4-2
//	 */
//	public int queryUploadNumByReferBatch(String concentratorNo, Date recordTime, 
//			Integer dataType) throws Exception {
//		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
//		return iAssignMeterDataGatherDao.queryUploadNumByReferBatch(concentratorNo, recordTime, dataType);
//	}
	
	/**
	 * 查询缺少基础档案信息的分配表数据对应的表号
	 * @param concentratorNo
	 * @param recordTime
	 * @param dataType
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-2
	 */
	public List<String> queryLackBaseinfoSeriousNum(String concentratorNo, Date recordTime, 
			Integer dataType) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryLackBaseinfoSeriousNum(concentratorNo, recordTime, dataType);
	}
	
	/**
	 * 分配表数据合规性检查
	 * @param meterData
	 * @return
	 * @author Xiaopeng
	 * @throws Exception 
	 * @date 2014-4-2
	 */
	public boolean checkMeterDataRational(IAssignMeterDataGather meterData) throws Exception {
		boolean rationalFlag = true;
		if(meterData != null) {
			//温度范围(0~99)检查
			if(meterData.getFontTemperature()<0 || meterData.getFontTemperature()>99) {
				rationalFlag = false;
			}
			if(meterData.getBackTmperature()<0 || meterData.getBackTmperature()>99) {
				rationalFlag = false;
			}
			//前板温度超过背板温度3度以上
			double tempDiff = CommercialHighPrecisionArith.subtract(meterData.getFontTemperature(), meterData.getBackTmperature());
			if(NumberSystemConversion.compareFloatValue(tempDiff, 3) > 0) {
				rationalFlag = false;
			}
		}
		return rationalFlag;
	}
	
	/**
	 * 根据任务批次信息查询分配表数据列表
	 * @param concentratorNo
	 * @param recordTime
	 * @param dataType
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-2
	 */
	public List<IAssignMeterDataGather> queryMeterDatasByBatch(String concentratorNo, 
			Date recordTime, Integer dataType) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryMeterDatasByBatch(concentratorNo, recordTime, dataType);
	}
	
	/**
	 * 根据任务批次信息查询不合规的分配表数据列表
	 * @param concentratorNo
	 * @param recordTime
	 * @param dataType
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-2
	 */
	public List<IAssignMeterDataGather> queryNonRationalDataByBatch(String concentratorNo, 
			Date recordTime, Integer dataType) throws Exception {
		//根据任务批次查询分配表数据列表
		List<IAssignMeterDataGather> meterDataList = this.queryMeterDatasByBatch(concentratorNo, recordTime, dataType);
		List<IAssignMeterDataGather> nonRationalMeterDataList = null;
		//校验分配表数据是否合规
		if(meterDataList!=null && meterDataList.size()>0) {
			nonRationalMeterDataList = new ArrayList<IAssignMeterDataGather>();
			for(IAssignMeterDataGather meterData: meterDataList) {
				//追加校验不合规的分配表数据
				if(!this.checkMeterDataRational(meterData)) {
					nonRationalMeterDataList.add(meterData);
				}
			}
		}
		return nonRationalMeterDataList;
	}
	
	/**
	 * 生成分配表数据的TXT文件
	 * @param meterDataList
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-4-3
	 */
	public ResponseMsg generateTxtDebugFile(List<IAssignMeterDataGather> meterDataList) throws Exception {
		//设置TXT文件保存路径
		File saveFolder = new File(this.tempSavePath);
		if(!saveFolder.exists()) {
			saveFolder.mkdirs();
		}
		//跟踪哪些用户下载了热表数据
		IUser sysUser = UserRoleUtil.getSysLoginUser();
		String randomFileName = CalendarUtils.parseDateToString(new Date(), "yyyyMMdd_HHmmssSSS");
		randomFileName += "_" + sysUser.getId() + "_" + sysUser.getUserID() + ".txt";
		//生成TXT文件
		RandomAccessFile txtFile = null;
		try {
			txtFile = new RandomAccessFile(new File(this.tempSavePath+"/"+randomFileName), "rw");
			if(meterDataList!=null && meterDataList.size()>0) {
				for(int index=0; index<meterDataList.size(); index++) {
					IAssignMeterDataGather meterData = meterDataList.get(index);
					//拼接热表数据字符串
					String meterDataDebugInfo = MeterDataTxtGenerator.genAssignMeterDataRecord(meterData);
					if(index < meterDataList.size()-1) {
						meterDataDebugInfo += "\n";
					}
					txtFile.writeBytes(meterDataDebugInfo.toString());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception(e.getMessage());
		} finally {
			if(txtFile != null) txtFile.close();
		}
		return ResponseMsg.getInstance(true, this.tempSavePath+"/"+randomFileName);
	}
	
	/**
	 * 分页查询分配表数据定制查询列表
	 * @param projectUID
	 * @param communityUID
	 * @param buildingUID
	 * @param recordTimeStart
	 * @param recordTimeEnd
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-12-9
	 */
	public ResultWithPageCond<AssignMeterDataCustomizedQuery> queryCustomizedQueryPage(String projectUID, 
			String communityUID, String buildingUID, Date recordTimeStart, 
			Date recordTimeEnd, PageCond pageCond) throws Exception {
		return iAssignMeterDataJdbcDao.queryCustomizedQueryPage(projectUID, communityUID, buildingUID, 
				recordTimeStart, recordTimeEnd, pageCond);
	}
	
	/**
	 * 查询单个楼栋的上传数据定制资料
	 * @param buildingUID
	 * @param recordDate
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2015-2-4
	 */
	public AssignMeterDataCustomizedQuery queryBuildingCustomizedQuery(String buildingUID, 
			Date recordDate) throws Exception {
		return iAssignMeterDataJdbcDao.queryBuildingCustomizedQuery(buildingUID, recordDate);
	}
	
	/**
	 * 通过定制查询列表查询与之关联的小区映射表
	 * @param customizedList
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-11-29
	 */
	public Map<String, String> queryReferCommunitysByCustomizedList(List<AssignMeterDataCustomizedQuery> 
			customizedList) throws Exception {
		List<String> communityIDList = null;
		if(customizedList!=null && customizedList.size()>0) {
			communityIDList = new ArrayList<String>();
			for(AssignMeterDataCustomizedQuery customizedQuery: customizedList) {
				communityIDList.add(customizedQuery.getCommunityUID());
			}
		}
		return iCommunityDao.queryIdNameMapByIDList(communityIDList);
	}
	
	/**
	 * 通过定制查询列表查询与之关联的楼栋映射表
	 * @param customizedList
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-11-29
	 */
	public Map<String, String> queryReferBuildingsByCustomizedList(List<AssignMeterDataCustomizedQuery> 
			customizedList) throws Exception {
		List<String> buildingIDList = null;
		if(customizedList!=null && customizedList.size()>0) {
			buildingIDList = new ArrayList<String>();
			for(AssignMeterDataCustomizedQuery customizedQuery: customizedList) {
				buildingIDList.add(customizedQuery.getBuildingUID());
			}
		}
		return iBuildingDao.queryIdNameMapByIDList(buildingIDList);
	}
	
	/**
	 * 根据定制查询特征信息(所属楼栋、抄表时间)统计分配表列表数据个数
	 * @param buildingUID
	 * @param recordTime
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-12-10
	 */
	public int countCustomizedAmDataList(String buildingUID, Date recordTime) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.countCustomizedAmDataList(buildingUID, recordTime);
	}
	
	/**
	 * 根据定制查询特征信息(所属楼栋、抄表时间)查询分配表数据列表
	 * @param buildingUID
	 * @param recordTime
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-12-14
	 */
	public ResultWithPageCond<IAssignMeterDataGather> queryCustomizedAmDataList(String buildingUID, 
			Date recordTime, PageCond pageCond) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryCustomizedAmDataList(buildingUID, recordTime, pageCond);
	}
	
	/**
	 * 查询与批次上传的上传时间不匹配的分配表数据ID
	 * @param concentratorNo
	 * @param recordTime
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2014-12-28
	 */
	public String queryNonMatchReadTime4Batch(String concentratorNo, Date recordTime) throws Exception {
		return this.iAssignMeterDataJdbcDao.queryNonMatchReadTime4Batch(concentratorNo, recordTime);
	}
	
	/**
	 * 统计分配表数据一个上传批次的成功上传数
	 * 成功上传数认定条件：
	 * (1)隶属于当前设定的上传批次，即具备相同的集中器号和抄表日期；
	 * (2)分配表数据上传日期与该批次上传日期一致；
	 * (3)抄表数据在档案中存在对应记录
	 * @param concentratorNo 集中器号
	 * @param recordTime 抄表日期
	 * @param readTime 上传时间
	 * @param dataType 数据类型
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2015-1-13
	 */
	public int countSuccessUploadNumReferBatch(String concentratorNo, Date recordTime, 
			Date readTime, Integer dataType) throws Exception {
		return this.iAssignMeterDataJdbcDao.countSuccessUploadNumReferBatch(concentratorNo, 
				recordTime, readTime, dataType);
	}

	
	/* 对未上传数据做处理,未上传数据中只要三天内上传的数据都算已成功上传了.
	 * @see com.nari.heatshare.service.IAssignMeterDataGatherService#getUnUploadRegisteData(java.lang.String, java.util.Date, java.util.Date)
	 */
	@SuppressWarnings("unchecked")
	public List<IAssignMeterDataGather> getUnUploadRegisteData(String concentratorNo, final Date recordTime,final Date readTime) throws Exception{//筛选数据
		 List<IAssignMeterDataGather> results = new ArrayList<IAssignMeterDataGather>();
//		//档案中的分配表号
		 //查询集中器ID
		IConcentrator concentrator = iConcentratorDao.queryByConcentratorNo(concentratorNo);
		if(concentrator==null) return results;
		String concentratorUID = concentrator.getId();
		//查询该集中旗下的分配表信息
		List<IAssignMeter> queryMetersByConcentratorIDs = iAssignMeterDao.queryMetersByConcentratorID(concentratorUID);//应该是集中器号
		//得到分配表信息中的分配表号的
		final List<String> documentMeters  = new ArrayList<String>();
		//使用Apache 默认的 集合变形工具   调用集合元素上的getSeriousNum,将得到的值
		Transformer invokerTransformer = TransformerUtils.invokerTransformer("getSeriousNum");
		CollectionUtils.collect(queryMetersByConcentratorIDs, invokerTransformer, documentMeters);
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		//查询某一日期的集中器上传情况,是一天内的上传情况
	ResultWithPageCond<IAssignMeterDataGather> queryMeterDataPageByUploadBatch = iAssignMeterDataGatherDao.queryMeterDataPageByUploadBatch(concentratorNo, recordTime, null, null, null, null);
	List<IAssignMeterDataGather> list = queryMeterDataPageByUploadBatch.getList();
	//筛选数据,将不符合的问题数据提取出来
	Predicate predicate = new Predicate(){
		public boolean evaluate(Object input) {
			IAssignMeterDataGather  assignMeterDataGather = (IAssignMeterDataGather) input;
			Date meterReadTime = assignMeterDataGather.getReadTime();
			if(readTime==null) return true;
			//此处应该使用RecordTime   在RecordTime 三天之前的就算该分配表未成功上传
			Calendar instance = Calendar.getInstance();
			instance.setTime(recordTime);
			instance.roll(Calendar.DAY_OF_YEAR, -3);
			Date time = instance.getTime();
			if(time.after(meterReadTime)&&documentMeters.contains(assignMeterDataGather.getSeriousNum())) {
				//数据的readTime与读表时间相差在三天之内,且档案中有该分配表的情况.
				return true;
			}else {
				return false;
			}
		}
	};
	List<String> uploadSeriesNum = (List<String>) CollectionUtils.collect(list,invokerTransformer);//已上传的所有分配表号
	List<String> subtract = ListUtils.subtract(documentMeters, uploadSeriesNum);
	//将list 中的元素的一些属性提取出来
//	 = (List<IAssignMeterDataGather>) CollectionUtils.find(list, predicate);
	List<IAssignMeterDataGather> find=(List<IAssignMeterDataGather>) CollectionUtils.select(list, predicate);
	//已上传的文件中 日期不合的筛选出来
	//没有上传的 也筛选出来
		for(String seriesNum: subtract) {
			IAssignMeterDataGather assignMeterDataGather = new IAssignMeterDataGather();
			assignMeterDataGather.setSeriousNum(seriesNum);
			//查出最后一次上传日期
			Date lastUploadDate = iAssignMeterDataGatherDao.queryLastUploadDate(seriesNum);
			assignMeterDataGather.setReadTime(lastUploadDate);
			find.add(assignMeterDataGather);
		}
		return find;
	}
	
	/**
	 * 获得问题数据(将问题数据筛选)
	 * @param concentratorNo 集中器号
	 * @param recordTime 集中器
	 * @throws Exception 
	 * */
	@Override
	public ArrayList<QuestionData>  getQuestionDatas(String concentratorNo, Date recordTime) throws Exception{
		ArrayList<QuestionData> datas = new ArrayList<QuestionData>();
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		ResultWithPageCond<IAssignMeterDataGather> queryMeterDataPageByUploadBatch = iAssignMeterDataGatherDao.queryMeterDataPageByUploadBatch(concentratorNo, recordTime, null, null, null, null);
		if(queryMeterDataPageByUploadBatch==null||queryMeterDataPageByUploadBatch.getList()==null) {
			return datas;
		}
		List<IAssignMeterDataGather> list = queryMeterDataPageByUploadBatch.getList();
		for(IAssignMeterDataGather assignMeterDataGather : list) {
			//遍历分配表数据,对有问题的数据进行标识
			double backTmperature = assignMeterDataGather.getBackTmperature();
			double fontTemperature = assignMeterDataGather.getFontTemperature();
			if(backTmperature>60||fontTemperature>60) {
				//如果前板温度或者后板温度大于60度 则为热阻塞
				QuestionData tempException = new QuestionData();
				tempException.setData(assignMeterDataGather);
				tempException.setFaultType(FaultType.TEMP_WRONG);
				datas.add(tempException);
				continue;
			}
			if(fontTemperature-backTmperature>3) {
				QuestionData tempException = new QuestionData();
				tempException.setData(assignMeterDataGather);
				tempException.setFaultType(FaultType.TEMP_WRONG);
				datas.add(tempException);
				continue;
			}
			if(fontTemperature>35&&backTmperature>35&&(Math.abs(fontTemperature-backTmperature)<=1)) {
				//前后板温度均大于35度 且温差小于1度
				//热阻塞
				QuestionData tempException = new QuestionData();
				tempException.setData(assignMeterDataGather);
				tempException.setFaultType(FaultType.HEAT_BLOCK);
				datas.add(tempException);
				continue;
			}
			String seriousNum = assignMeterDataGather.getSeriousNum();
			//分配表号
			if(StringUtils.isBlank(seriousNum)) continue;
			if(QuestionDataSet.batteryExceptionContain(seriousNum)) {
				//电池异常警告
					QuestionData tempException = new QuestionData();
					tempException.setData(assignMeterDataGather);
					tempException.setFaultType(FaultType.LOW_BATTERY);
					datas.add(tempException);
					continue;
			}
			if(QuestionDataSet.commExceptionContain(seriousNum)) {
				QuestionData tempException = new QuestionData();
				tempException.setData(assignMeterDataGather);
				tempException.setFaultType(FaultType.COMM_WRONG);
				datas.add(tempException);
			}
		}
		return datas;
	}
	
	private void putBugs(List<IAssignMeterDataGather> list) {
		IAssignMeterDataGather bug1 = new IAssignMeterDataGather();
		bug1.setSeriousNum("121212");
		bug1.setFontTemperature(98);
		bug1.setBackTmperature(35);
		list.add(bug1);
		IAssignMeterDataGather bug2 = new IAssignMeterDataGather();
		bug2.setSeriousNum("2332453");
		bug2.setFontTemperature(37.3);
		bug2.setBackTmperature(37.1);
		list.add(bug2);
	}
	
	
	
	

	/**
	 * @return the iCommunityDao
	 */
 	public ICommunityDao getiCommunityDao() {
		return iCommunityDao;
	}

	/**
	 * @param iCommunityDao the iCommunityDao to set
	 */
	public void setiCommunityDao(ICommunityDao iCommunityDao) {
		this.iCommunityDao = iCommunityDao;
	}

	/**
	 * @return the iBuildingDao
	 */
	public IBuildingDao getiBuildingDao() {
		return iBuildingDao;
	}

	/**
	 * @param iBuildingDao the iBuildingDao to set
	 */
	public void setiBuildingDao(IBuildingDao iBuildingDao) {
		this.iBuildingDao = iBuildingDao;
	}

	/**
	 * @return the iHeatRoomDao
	 */
	public IHeatRoomDao getiHeatRoomDao() {
		return iHeatRoomDao;
	}

	/**
	 * @param iHeatRoomDao the iHeatRoomDao to set
	 */
	public void setiHeatRoomDao(IHeatRoomDao iHeatRoomDao) {
		this.iHeatRoomDao = iHeatRoomDao;
	}

	/**
	 * @return the iAssignMeterDao
	 */
	public IAssignMeterDao getiAssignMeterDao() {
		return iAssignMeterDao;
	}

	/**
	 * @param iAssignMeterDao the iAssignMeterDao to set
	 */
	public void setiAssignMeterDao(IAssignMeterDao iAssignMeterDao) {
		this.iAssignMeterDao = iAssignMeterDao;
	}

	public IConcentratorDao getiConcentratorDao() {
		return iConcentratorDao;
	}

	public void setiConcentratorDao(IConcentratorDao iConcentratorDao) {
		this.iConcentratorDao = iConcentratorDao;
	}

	/**
	 * @return the iAssignMeterDataJdbcDao
	 */
	public IAssignMeterDataJdbcDao getiAssignMeterDataJdbcDao() {
		return iAssignMeterDataJdbcDao;
	}

	/**
	 * @param iAssignMeterDataJdbcDao the iAssignMeterDataJdbcDao to set
	 */
	public void setiAssignMeterDataJdbcDao(
			IAssignMeterDataJdbcDao iAssignMeterDataJdbcDao) {
		this.iAssignMeterDataJdbcDao = iAssignMeterDataJdbcDao;
	}

	/**
	 * @return the iAssignMeterDataStatisticsService
	 */
	public IAssignMeterDataStatisticsService getiAssignMeterDataStatisticsService() {
		return iAssignMeterDataStatisticsService;
	}

	/**
	 * @param iAssignMeterDataStatisticsService the iAssignMeterDataStatisticsService to set
	 */
	public void setiAssignMeterDataStatisticsService(
			IAssignMeterDataStatisticsService iAssignMeterDataStatisticsService) {
		this.iAssignMeterDataStatisticsService = iAssignMeterDataStatisticsService;
	}

	/**
	 * @return the tempSavePath
	 */
	public String getTempSavePath() {
		return tempSavePath;
	}

	/**
	 * @param tempSavePath the tempSavePath to set
	 */
	public void setTempSavePath(String tempSavePath) {
		this.tempSavePath = tempSavePath;
	}

	@Override
	public ArrayList<String> getQuestionDataIDs(
			ArrayList<QuestionData> questionDatas) {
		Transformer transformer = new Transformer() {
			@Override
			public Object transform(Object input) {
				QuestionData questionData = (QuestionData) input;
				IAssignMeterDataGather data = questionData.getData();
				if(data==null) return null;
				return data.getId();
			}
		};
		return (ArrayList<String>) CollectionUtils.collect(questionDatas, transformer);
	}
	
	@Override
	public ResultWithPageCond<AssignDataWithInfo> queryAssignDataWithInfo(
			String buildingUID, Date recordTime, PageCond pageCond)
			throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryAssignDataWithInfo(buildingUID, recordTime, pageCond);
	}

	
	
	
	
	
	/**
	 * 分页查询分配表数据列表
	 * @param seriousNum 分配表号
	 * @param startDate 起始抄表时间
	 * @param endDate 终止抄表时间
	 * @param pageCond
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-9-2
	 */
	public ResultWithPageCond<IAssignMeterDataGather> queryMeterDataAllotPage(
			String seriousNum, Date startDate, Date endDate, PageCond pageCond)
			throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryMeterDataAllotPage(seriousNum, startDate, endDate, pageCond);
		
	}
	
	/**
	 * 查询所有项目信息，并对结果集排序
	 * 
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-8-8
	 */
	public List<IAssignMeterDataGather> queryAllSeriousNumInOrderList(String seriousNum, 
			Date recordTime) throws Exception {
		IAssignMeterDataGatherDao iAssignMeterDataGatherDao = (IAssignMeterDataGatherDao) this.getiGenericDao();
		return iAssignMeterDataGatherDao.queryMeterDatasBySeriousNumList(seriousNum, recordTime);
	}


}
